// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0


export component TestCase inherits Window {
    width: 600px;
    height: 600px;

    in-out property <string> r;
    in property <bool> enabled <=> right-gesture.enabled;
    out property ta_hover <=> ta.has-hover;
    out property ta_pressed <=> ta.pressed;
    out property down-swiping <=> down-gesture.swiping;
    out property left-swiping <=> left-gesture.swiping;
    out property right-swiping <=> right-gesture.swiping;

    function distance(a: Point, b: Point) -> float {
        return sqrt((a.x / 1px - b.x / 1px).pow(2) + (a.y / 1px - b.y / 1px).pow(2));
    }
    public function invoke_cancel() {
        left-gesture.cancel()
    }

    down-gesture := SwipeGestureHandler {
        handle-swipe-down: true;
        handle-swipe-left: false;
        swiped => {
            r += "S1(" + distance(self.current-position, self.pressed-position) + ")";
        }
        cancelled => {
            r += "C1(" + distance(self.current-position, self.pressed-position) + ")";
        }
        VerticalLayout {
            left-gesture := SwipeGestureHandler {
                handle-swipe-left: true;
                swiped => {
                    r += "S2(" + distance(self.current-position, self.pressed-position) + ")";
                }
                moved => {
                    r += "M2(" + distance(self.current-position, self.pressed-position) + ")";
                }
                cancelled => {
                    r += "C2(" + distance(self.current-position, self.pressed-position) + ")";
                }
            }

            right-gesture := SwipeGestureHandler {
                handle-swipe-right: true;
                ta := TouchArea {
                    clicked => {
                        r += "clicked()"
                    }
                }

                swiped => {
                    r += "S3(" + distance(self.current-position, self.pressed-position) + ")";
                }
            }
        }
    }

    init => {
        // Just make sure it doesn't crash the interpreter
        left-gesture.cancel();
    }
}

/*
```rust
let instance = TestCase::new().unwrap();

assert_eq!(instance.get_enabled(), true);
assert_eq!(instance.get_r(), "");
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);

use slint::{platform::WindowEvent, LogicalPosition, platform::PointerEventButton};

// click
slint_testing::send_mouse_click(&instance, 500., 500.);
assert_eq!(instance.get_r(), "clicked()");
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
instance.set_r("".into());


// Down
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(4.0, 4.0) });
assert_eq!(instance.get_ta_hover(), false);
slint_testing::mock_elapsed_time(20);
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(300.0, 400.0) });
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(300.0, 400.0), button: PointerEventButton::Left });
slint_testing::mock_elapsed_time(20);
assert_eq!(instance.get_ta_pressed(), false); // because we might recognize it as a gesture
assert_eq!(instance.get_ta_hover(), true, "must be hover");
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);

instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(299.0, 402.0) });
slint_testing::mock_elapsed_time(20);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);

instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(298.0, 452.0) });
slint_testing::mock_elapsed_time(20);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_down_swiping(), true);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
slint_testing::mock_elapsed_time(220);

instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(350.0, 482.0) });
slint_testing::mock_elapsed_time(20);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_down_swiping(), true);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_r(), "");

instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(316.0, 463.0) });
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(316.0, 463.0), button: PointerEventButton::Left });
assert_eq!(instance.get_r(), "S1(65)");
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
instance.set_r("".into());

// FIXME: this shouldn't be necessary, but otherwise we don't send exit event to the toucharea
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(316.0, 463.0) });

// Left
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 100.0) });
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
slint_testing::mock_elapsed_time(20);
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(100.0, 100.0), button: PointerEventButton::Left });
slint_testing::mock_elapsed_time(20);
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_r(), "");
slint_testing::mock_elapsed_time(20);
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(80.0, 100.0) });
slint_testing::mock_elapsed_time(80);
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(65.0, 112.0) });
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_left_swiping(), true);
assert_eq!(instance.get_r(), "M2(37)");
instance.window().dispatch_event(WindowEvent::PointerExited);
assert_eq!(instance.get_r(), "M2(37)C2(37)");
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_ta_hover(), false);


// Left again but cancel in the middle
instance.set_r("".into());
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 100.0) });
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
slint_testing::mock_elapsed_time(20);
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(100.0, 100.0), button: PointerEventButton::Left });
slint_testing::mock_elapsed_time(120);
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_r(), "");
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(80.0, 100.0) });
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_left_swiping(), true);
assert_eq!(instance.get_r(), "M2(20)");
instance.invoke_invoke_cancel();
assert_eq!(instance.get_r(), "M2(20)C2(20)");
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_ta_hover(), false);
slint_testing::mock_elapsed_time(120);
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(60.0, 100.0) });
slint_testing::mock_elapsed_time(120);
instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(100.0, 100.0), button: PointerEventButton::Left });
slint_testing::mock_elapsed_time(120);
assert_eq!(instance.get_r(), "M2(20)C2(20)");
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
assert_eq!(instance.get_ta_hover(), false);
```

```rust
use slint::{platform::WindowEvent, LogicalPosition, platform::PointerEventButton};

// swipe two swipe area at the same time
let instance = TestCase::new().unwrap();

assert_eq!(instance.get_enabled(), true);
assert_eq!(instance.get_r(), "");
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);

instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(100.0, 400.0) });
assert_eq!(instance.get_ta_hover(), true);
instance.window().dispatch_event(WindowEvent::PointerPressed { position: LogicalPosition::new(100.0, 400.0), button: PointerEventButton::Left });
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_ta_pressed(), false);
// wait a very long time
slint_testing::mock_elapsed_time(1300);
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_ta_pressed(), true);
// up right
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(130.0, 380.0) });
assert_eq!(instance.get_r(), "");
assert_eq!(instance.get_ta_hover(), false, "hover was cancelled");
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), true);
// now down right: this cancel the previous swipe
instance.window().dispatch_event(WindowEvent::PointerMoved { position: LogicalPosition::new(110.0, 519.0) });
assert_eq!(instance.get_r(), "");
assert_eq!(instance.get_ta_hover(), false);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_down_swiping(), true);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false, "got cancelled");

instance.window().dispatch_event(WindowEvent::PointerReleased { position: LogicalPosition::new(220.0, 519.0), button: PointerEventButton::Left });
assert_eq!(instance.get_r(), "S1(169)");
assert_eq!(instance.get_ta_hover(), true);
assert_eq!(instance.get_ta_pressed(), false);
assert_eq!(instance.get_down_swiping(), false);
assert_eq!(instance.get_left_swiping(), false);
assert_eq!(instance.get_right_swiping(), false);
```

```cpp
using slint::PointerEventButton;
auto handle = TestCase::create();
const TestCase &instance = *handle;


// Left and cancel in the middle
instance.window().dispatch_pointer_press_event(slint::LogicalPosition({100.0, 100.0}), PointerEventButton::Left);
assert_eq(instance.get_ta_hover(), false);
assert_eq(instance.get_down_swiping(), false);
assert_eq(instance.get_left_swiping(), false);
assert_eq(instance.get_right_swiping(), false);
slint_testing::mock_elapsed_time(120);
instance.window().dispatch_pointer_move_event(slint::LogicalPosition({ 80.0, 100.0 }));
assert_eq(instance.get_ta_hover(), false);
assert_eq(instance.get_down_swiping(), false);
assert_eq(instance.get_right_swiping(), false);
assert_eq(instance.get_left_swiping(), true);
assert_eq(instance.get_r(), "M2(20)");
instance.invoke_invoke_cancel();
assert_eq(instance.get_r(), "M2(20)C2(20)");
assert_eq(instance.get_down_swiping(), false);
assert_eq(instance.get_left_swiping(), false);
assert_eq(instance.get_right_swiping(), false);
assert_eq(instance.get_ta_hover(), false);
slint_testing::mock_elapsed_time(120);
instance.window().dispatch_pointer_move_event(slint::LogicalPosition({ 60.0, 100.0 }));
slint_testing::mock_elapsed_time(120);
instance.window().dispatch_pointer_release_event(slint::LogicalPosition({40.0, 100.0}), PointerEventButton::Left);
slint_testing::mock_elapsed_time(120);
assert_eq(instance.get_r(), "M2(20)C2(20)");
assert_eq(instance.get_down_swiping(), false);
assert_eq(instance.get_left_swiping(), false);
assert_eq(instance.get_right_swiping(), false);
assert_eq(instance.get_ta_hover(), false);
```

*/
